//@author A0101200R

package testcases;

import static org.junit.Assert.*;
import logic.ScheduleAdder;
import logic.ScheduleDisplay;
import logic.ScheduleModify;
import logic.ScheduleSearcher;
import logic.ScheduleSorter;
import logic.ScheduleUndoer;

import org.junit.Test;

import storage.ScheduleEvent;
import storage.Storage;

public class ScheduleModifyTest {
	
	// list of constants
	private static final int EVENT_TYPE_FLOATING = 0;
	private static final int EVENT_TYPE_DEADLINE = 1;
	private static final int EVENT_TYPE_TIMED = 2;
	private static final String WHITE_SPACE = " ";
	
	// list of inputs
	private static final String modifiedName = "n newTaskname ";
	private static final String modifiedDate1 = "d today ";
	private static final String modifiedDate2 = "d 15122014 ";
	private static final String modifiedStartTime = "st 1000 ";
	private static final String modifiedEndTime = "et 2000 ";
	private static final String modifiedAll = "newtimedtask" + "01012015" + modifiedStartTime + modifiedEndTime;
	
	// list of error messages
	private static final String ERROR_INVALID_INDEX = "Error! The index you want to display is invalid.";
	private static final String ERROR_NON_NUMERIC_INDEX = "Error! The index you have keyed in is not a number.";
	private static final String ERROR_NO_START_TIME = "You did not enter a start time.";
	private static final String ERROR_NO_END_TIME = "You did not enter a end time.";
	private static final String ERROR_INVALID_PARAMETER = "The parameter you keyed in to modify the details is not valid.";
	private static final String ERROR_UNABLE_TO_MODIFY = "Task could not be modified";
	
	// list of variables from other classes
	Storage storage = new Storage("testDisplay.txt");
	ScheduleAdder adder = new ScheduleAdder(storage);
	ScheduleSorter sorter = new ScheduleSorter(storage);
	ScheduleUndoer undoer = new ScheduleUndoer(storage); 
	ScheduleSearcher searcher = new ScheduleSearcher(storage, sorter);
	ScheduleModify modifier = new ScheduleModify(storage, adder, undoer);
	ScheduleDisplay display = new ScheduleDisplay(storage, sorter, searcher);
	
	ScheduleEvent floatingTask, deadlineTask1, deadlineTask2, timedTask;
	
	private String addTimed() {
		timedTask = new ScheduleEvent(EVENT_TYPE_TIMED, "test for timed task", "01052014", "0900", "1500");
		storage.addEvent(timedTask);
		int index = storage.getEventIndex(timedTask) + 1;
		String s = Integer.toString(index) + WHITE_SPACE;
		
		return s;
	}

	private String addDeadline1() {
		deadlineTask1 = new ScheduleEvent(EVENT_TYPE_DEADLINE, "test for deadline task 1", "02052014", "1500");
		storage.addEvent(deadlineTask1);
		int index = storage.getEventIndex(deadlineTask1) + 1;
		String s = Integer.toString(index) + WHITE_SPACE;
		
		return s;
	}
	
	private String addDeadline2() {
		deadlineTask2 = new ScheduleEvent(EVENT_TYPE_DEADLINE, "test for deadline task 2", "03052014");
		storage.addEvent(deadlineTask2);
		int index = storage.getEventIndex(deadlineTask2) + 1;
		String s = Integer.toString(index) + WHITE_SPACE;
		
		return s;
	}
	
	private String addFloat() {
		floatingTask = new ScheduleEvent(EVENT_TYPE_FLOATING, "test for floating task", "99999999");
		storage.addEvent(floatingTask);
		int index = storage.getEventIndex(floatingTask) + 1;
		String s = Integer.toString(index) + WHITE_SPACE;
		
		return s;
	}
	
	private String addFloat2() {
		floatingTask = new ScheduleEvent(EVENT_TYPE_FLOATING, "test for floating task 2", "99999999");
		storage.addEvent(floatingTask);
		int index = storage.getEventIndex(floatingTask) + 1;
		String s = Integer.toString(index) + WHITE_SPACE;
		
		return s;
	}
	
	private String modifyTasks(String index, String input) {
		String output  = null;
		int n;

		output = modifier.modifyEvents(index + input);
		
		try {
			n = Integer.parseInt(index.trim()) - 1;
		} catch (NumberFormatException e) {
			return ERROR_NON_NUMERIC_INDEX;
		} 
		
		if (input.equals(modifiedName)) {
			output = storage.getEvent(n).toString();
		} else if (input.equals(modifiedDate1)) {
			output = storage.getEvent(0).toString();
		} else if (input.equals(modifiedDate2)) {
			output = storage.getEvent(1).toString();
		} else if (input.equals(modifiedAll)) {
			output = storage.getEvent(2).toString();
		} 
		
		return output;
	}
	
	@Test
	public void testModify() {
		storage.clearAllEvents();
		String indexTimed = addTimed();
		String indexDeadline1 = addDeadline1();
		String indexDeadline2 = addDeadline2();
		String indexFloating = addFloat();
		String indexFloating2 = addFloat2();
		
		String expected, actual;
		
		expected = modifyTasks(indexFloating, modifiedName);
		actual = display.displayEvents(indexFloating.trim()).toString();
		assertEquals(expected, actual);
		
		expected = modifyTasks(indexFloating, modifiedDate1);
		actual = display.displayEvents("1").toString();
		assertEquals(expected, actual);
		
		expected = modifyTasks(indexDeadline2, modifiedDate2);
		actual = display.displayEvents("2").toString();
		assertEquals(expected, actual);
		
		expected = modifyTasks(indexTimed, modifiedAll);
		actual = display.displayEvents("3").toString();
		assertEquals(expected, actual);
		
		actual = display.displayEvents("10").toString();
		assertEquals(ERROR_INVALID_INDEX, actual);
		
		actual = modifyTasks("str", modifiedAll);
		assertEquals(ERROR_NON_NUMERIC_INDEX, actual);
		
		actual = modifyTasks(indexDeadline1, "s 1300 ");
		assertEquals(ERROR_INVALID_PARAMETER, actual);
		
		actual = modifyTasks(indexDeadline1, "st et ");
		assertEquals(ERROR_NO_START_TIME, actual);
		
		actual = modifyTasks(indexDeadline1, "et st ");
		assertEquals(ERROR_NO_END_TIME, actual);
		
		actual = modifyTasks(indexDeadline1, "d todya ");
		assertEquals(ERROR_UNABLE_TO_MODIFY, actual);
		
		actual = modifyTasks(indexFloating2, "st 1300 ");
		assertEquals(ERROR_UNABLE_TO_MODIFY, actual);
	}

}
